﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace AutomatedDecisionMaking.Class.Algorithms
{
    class LaplaceAlgorithm
    {
        private readonly DecisionMatrix _mDecisionMatrix;    /// Macierz decyzji
        private readonly List<double> _mLaplaceValues;       /// Wartości po wymnożeniu przez wagi laplacea
        private readonly List<string> _mStrLaplaceValues;    /// Wartośch po ważeniu ze współczynnikami Laplace'a
        private double _mLaplaceWeight;                      /// Waga laplace'a zależna od ilości scenariuszy
        private double _mMaxLaplaceVal;                      /// Największa wartości po wazeniu
        private string _mDecision;                           /// Podjęta decyzja

        /// <summary>
        /// Konstruktor algorytmu realizującego kryterium Laplace'a.
        /// </summary>
        /// <param name="decisionMatrix">Macierz decyzji wprowadzona porzez użytkownika</param>
        public LaplaceAlgorithm(DecisionMatrix decisionMatrix)
        {
            _mStrLaplaceValues = new List<string>();
            _mLaplaceValues = new List<double>();
            _mDecisionMatrix = decisionMatrix;
        }

        /// <summary>
        /// Reset całego algorytmu
        /// </summary>
        public void Reset()
        {
            _mStrLaplaceValues.Clear();
            _mLaplaceValues.Clear();
        }

        /// <summary>
        /// Uruchomienie algorytmu i rozwiązanie postawionego zadania
        /// </summary>
        public void CalculateSolution()
        {
            CalculateLaplaceWeights();
            //List<double> listMaxValue = new List<double>();
            for (int i = 0; i < _mDecisionMatrix.Value.Count; ++i)
            {
                string element = _mDecisionMatrix.DecisionList.ElementAt(i);
                double laplaceVal = _mDecisionMatrix.Value[i].Sum()*_mLaplaceWeight;
                _mStrLaplaceValues.Add(element + " : wartość Laplace'a = " + laplaceVal);
                _mLaplaceValues.Add(laplaceVal);
            }

            _mMaxLaplaceVal = _mLaplaceValues.Max();
            _mDecision = _mDecisionMatrix.DecisionList.ElementAt(_mLaplaceValues.FindIndex(w => w == _mMaxLaplaceVal));
        }

        /// <summary>
        /// Dostęp do macierzy decyzji
        /// </summary>
        /// <returns>Macierz decyzji</returns>
        public DecisionMatrix GetDecisionMatrix()
        {
            return _mDecisionMatrix;
        }

        /// <summary>
        /// Pobranie wagi Laplace'a
        /// </summary>
        /// <returns>Waga Laplace'a</returns>
        public double GetLaplaceWeight()
        {
            return _mLaplaceWeight;
        }

        /// <summary>
        /// Dostęp do decyzji podjętej przez algorytm na drodze wnioskowania
        /// </summary>
        /// <returns>Podjęta decyzj</returns>
        public string GetDecision()
        {
            return _mDecision;
        }

        /// <summary>
        /// Pobranie wartości odpowiadającej podjętej decyzji
        /// </summary>
        /// <returns>Wartośc dla podjętej decyzji</returns>
        public double GetMaxLaplaceValue()
        {
            return _mMaxLaplaceVal;
        }

        /// <summary>
        /// Pobranie wartości maksymalnych po ważeniu ze współczynnikami Laplace'a wraz z decyzjami
        /// </summary>
        /// <returns>Wartości ważone</returns>
        public List<string> GetMaxLaplaceValuesStr()
        {
            return _mStrLaplaceValues;
        }

        /// <summary>
        /// Pobranie wartości maksymalnych po ważeniu ze współczynnikami Laplace'a
        /// </summary>
        /// <returns>Wartości ważone</returns>
        public List<double> GetMaxLaplaceValues()
        {
            return _mLaplaceValues;
        }

        /// <summary>
        /// Wyznaczenie wag Laplace'a
        /// </summary>
        private void CalculateLaplaceWeights()
        {
            _mLaplaceWeight = (1.0 / Convert.ToDouble(_mDecisionMatrix.ScenarioList.Count));
        }
    }
}
